#include "scene.hpp"
#include <boost/concept_check.hpp>

void Scene::addSphere ( ptree & tree )
{
    PrimSphere sphere;
    sphere._radius =  tree.get< real_t>( "radius");

    sphere._position.xyz(
                            tree.get< real_t>("position.x"),
                            tree.get< real_t>("position.y"),
                            tree.get< real_t>("position.z")
                        );
    sphere.material.ParsePtree( tree.get_child("material"));

    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimSphere( sphere);
}

void Scene::addTor ( ptree & tree )
{
    PrimTor tor;
    real_t outer = tree.get< real_t>( "radius_outer");
    real_t inner = tree.get< real_t>( "radius_inner");

    tor.SetRadius( inner, outer);

    Vector tmp;

    tmp.xyz
        (
            tree.get< real_t>("position.x"),
            tree.get< real_t>("position.y"),
            tree.get< real_t>("position.z")
        );
    tor.SetPosition( tmp);

/*    tmp.xyz
        (
            tree.get< real_t>("normal.x"),
            tree.get< real_t>("normal.y"),
            tree.get< real_t>("normal.z")
        );
*/
    tmp.xyz( 0.0 , 0.0, 1.0);    
    tor.SetNormal( tmp);
     

    tor.material.ParsePtree( tree.get_child("material"));
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTor( tor);
}


void Scene::addCube ( ptree & tree )
{
    PrimTriangle triangle;

    triangle.material.ParsePtree( tree.get_child("material"));
    real_t size = tree.get< real_t>("size")/2;

    Vector position;
    position.xyz
        (
            tree.get< real_t>("position.x"),
            tree.get< real_t>("position.y"),
            tree.get< real_t>("position.z")
        );
    
    Vector dir1( 0.0 , 1.0, 0.0  ),  dir2( 1.0,0.0,0.0), dir3;
    dir3 = dir1 * dir2;
        
    Vector p1,p2,p3,p4;
    // нижняя грань
    p1 = position  + ( - dir1 - dir2 - dir3 ) * size;
    p2 = position  + ( - dir1 - dir2 + dir3 ) * size;
    p3 = position  + ( - dir1 + dir2 + dir3 ) * size;
    p4 = position  + ( - dir1 + dir2 - dir3 ) * size;

    triangle.SetPoints( p1,p2,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);

    triangle.SetPoints( p2,p3,p4);

    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
    
    // верхняя
    p1 = position  + (  dir1 - dir2 - dir3 ) * size;
    p2 = position  + (  dir1 - dir2 + dir3 ) * size;
    p3 = position  + (  dir1 + dir2 + dir3 ) * size;
    p4 = position  + (  dir1 + dir2 - dir3 ) * size;
    
    triangle.SetPoints( p2,p1,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
    
    triangle.SetPoints( p3,p2,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
    //слево
    p1 = position  + ( - dir1 - dir2 - dir3 ) * size;
    p2 = position  + ( - dir1 - dir2 + dir3 ) * size;
    p3 = position  + ( + dir1 - dir2 + dir3 ) * size;
    p4 = position  + ( + dir1 - dir2 - dir3 ) * size;
    
    triangle.SetPoints( p2,p1,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
    
    triangle.SetPoints( p3,p2,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
    // справо
    p1 = position  + ( - dir1 + dir2 - dir3 ) * size;
    p2 = position  + ( - dir1 + dir2 + dir3 ) * size;
    p3 = position  + ( + dir1 + dir2 + dir3 ) * size;
    p4 = position  + ( + dir1 + dir2 - dir3 ) * size;
    
    triangle.SetPoints( p1,p2,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
    
    triangle.SetPoints( p2,p3,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
    
    // передняя
    p1 = position  + ( - dir1 - dir2 - dir3 ) * size;
    p2 = position  + ( - dir1 + dir2 - dir3 ) * size;
    p3 = position  + ( + dir1 + dir2 - dir3 ) * size;
    p4 = position  + ( + dir1 - dir2 - dir3 ) * size;
    
    triangle.SetPoints( p1,p2,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
    
    triangle.SetPoints( p2,p3,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
    
    // задняя
    p1 = position  + ( - dir1 - dir2 + dir3 ) * size;
    p2 = position  + ( - dir1 + dir2 + dir3 ) * size;
    p3 = position  + ( + dir1 + dir2 + dir3 ) * size;
    p4 = position  + ( + dir1 - dir2 + dir3 ) * size;
    triangle.SetPoints( p2,p1,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
    
    triangle.SetPoints( p3,p2,p4);
    
    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
}

void Scene::addTriangle( ptree & tree)
{
    PrimTriangle triangle;
    Vector p1,p2,p3;
    p1.xyz(
            tree.get< real_t>("p1.x"),
            tree.get< real_t>("p1.y"),
            tree.get< real_t>("p1.z")
          );
    p2.xyz(
            tree.get< real_t>("p2.x"),
            tree.get< real_t>("p2.y"),
            tree.get< real_t>("p2.z")
          );

    p3.xyz(
            tree.get< real_t>("p3.x"),
            tree.get< real_t>("p3.y"),
            tree.get< real_t>("p3.z")
        );
        
    triangle.SetPoints( p1, p2 ,p3);
    triangle.material.ParsePtree( tree.get_child("material"));

    primitive.resize( primitive.size()+1);
    primitive[ primitive.size()-1] = new PrimTriangle( triangle);
}